package com.duobaoyu.dby.supply.biz.strategy.message.order.logistics;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.duobaoyu.dby.channel.adapter.bean.message.order.OrderMessage;
import com.duobaoyu.dby.channel.adapter.enums.BizMessageTypeEnum;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.order.OrderStatusEnum;
import com.duobaoyu.dby.channel.boundary.bean.order.param.LogisticQueryParam;
import com.duobaoyu.dby.channel.boundary.bean.order.result.LogisticQueryResult;
import com.duobaoyu.dby.channel.boundary.template.SupplyChannelTemplate;
import com.duobaoyu.dby.channel.common.util.SupplyCollectionUtils;
import com.duobaoyu.dby.supply.biz.constant.OperateSourceConstants;
import com.duobaoyu.dby.supply.biz.constant.OrderOperateConstants;
import com.duobaoyu.dby.supply.biz.producer.SupplyChainMQProducer;
import com.duobaoyu.dby.supply.biz.service.order.OrderService;
import com.duobaoyu.dby.supply.biz.strategy.message.order.base.BaseOrderAsyncHandler;
import com.duobaoyu.dby.supply.common.biz.bo.message.ChannelMessageBO;
import com.duobaoyu.dby.supply.db.entity.order.Order;
import com.duobaoyu.dby.supply.db.entity.order.OrderLogistics;
import com.duobaoyu.dby.supply.db.repository.order.OrderLogisticsRepository;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 物流消息同步
 *
 * @author fengshaoyu
 * @version 1.0.0
 * @date 2023/10/21 10:43
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class LogisticsOrderInfoAsyncHandler extends BaseOrderAsyncHandler {

	private final OrderService orderService;
	private final OrderLogisticsRepository orderLogisticsRepository;
	private final SupplyChannelTemplate supplyChannelTemplate;
	private final SupplyChainMQProducer supplyChainMQProducer;

	@Override
	protected Set<String> channelCodes() {
		return Sets.newHashSet(ChannelCodeEnum.ALIBABA_DISTRIBUTION.getValue(),
				ChannelCodeEnum.ONE_WALLET.getValue(),
				ChannelCodeEnum.LINKED_MALL.getValue(),
				ChannelCodeEnum.JD_VOP.getValue());
	}

	@Override
	protected Set<Integer> bizMessageTypes() {
		return Sets.newHashSet(BizMessageTypeEnum.LOGISTICS_STATUS_CHANGE.getValue());
	}

	@Override
	protected Boolean executeHandler(ChannelMessageBO channelMessage, Object beforeResult) {
		List<OrderMessage> orderMessages = this.getMessage(channelMessage);
		List<Order> orderList = this.getOrderList(channelMessage);
		if (CollectionUtils.isEmpty(orderList)) {
			log.info("message:{},channelCode:{},data:{}", "物流回调失败", channelMessage.getChannelCode(), JSON.toJSONString(channelMessage));
			return Boolean.FALSE;
		}

		for (Order order : orderList) {
			OrderMessage orderMessage = orderMessages.stream().filter(item -> {
				Boolean channelOrderSn = StringUtils.isNotBlank(item.getChannelOrderSn()) ? Objects.equals(item.getChannelOrderSn(), order.getChannelOrderSn()) : Boolean.TRUE;
				Boolean channelOrderParentSn = StringUtils.isNotBlank(item.getChannelOrderParentSn()) ? Objects.equals(item.getChannelOrderParentSn(), order.getChannelOrderParentSn()) : Boolean.TRUE;
				Boolean channelTradeOrderSn = StringUtils.isNotBlank(item.getChannelTradeOrderSn()) ? Objects.equals(item.getChannelOrderSn(), order.getChannelTradeOrderSn()) : Boolean.TRUE;
				return channelOrderSn && channelOrderParentSn && channelTradeOrderSn;
			}).findFirst().orElse(null);
			if (ObjectUtils.isEmpty(orderMessage)) {
				continue;
			}

			List<OrderLogistics> orderLogisticsList = null;
			try {
				LogisticQueryParam logisticQueryParam = LogisticQueryParam.builder()
						.channelCode(order.getChannelCode())
						.orderTradeSn(order.getOrderTradeSn())
						.channelOrderSn(order.getChannelOrderSn())
						.channelOrderParentSn(order.getChannelOrderParentSn())
						.channelTradeOrderSn(order.getChannelTradeOrderSn())
						.build();
				List<LogisticQueryResult> logisticResultList = supplyChannelTemplate.queryLogisticInfoList(Collections.singletonList(logisticQueryParam));
				orderLogisticsList = logisticResultList.stream().map(LogisticQueryResult::getDeliveryInfoList).flatMap(Collection::stream).map(item -> {
					OrderLogistics orderLogistics = new OrderLogistics();
					orderLogistics.setOrderSn(order.getOrderSn());
					orderLogistics.setDeliveryOrderSn(item.getDeliveryOrderSn());
					orderLogistics.setDeliveryCarrier(item.getDeliveryCarrier());
					return orderLogistics;
				}).collect(Collectors.toList());

				List<OrderLogistics> orderLogisticsOldList = orderLogisticsRepository.list(Wrappers.<OrderLogistics>lambdaQuery().eq(OrderLogistics::getOrderSn, order.getOrderSn()));
				Iterator<OrderLogistics> iterator = orderLogisticsList.iterator();
				while (iterator.hasNext()) {
					OrderLogistics orderLogistics = iterator.next();
					for (OrderLogistics orderLogisticsOld : orderLogisticsOldList) {
						if (Objects.equals(orderLogistics.getOrderSn(), orderLogisticsOld.getOrderSn()) &&
								Objects.equals(orderLogistics.getDeliveryOrderSn(), orderLogisticsOld.getDeliveryOrderSn()) &&
								Objects.equals(orderLogistics.getDeliveryCarrier(), orderLogisticsOld.getDeliveryCarrier())) {
							iterator.remove();
						}
					}
				}
			} catch (Exception e) {
				log.warn("message:{},data:{},channelCode:{}", "物流信息同步失败", e, order.getChannelCode());
			}

			orderLogisticsRepository.saveBatch(orderLogisticsList);
			OrderStatusEnum orderSubStatusOld = OrderStatusEnum.getOrderSubStatusEnum(order.getOrderStatus());
			OrderStatusEnum orderSubStatusNew = OrderStatusEnum.getOrderSubStatusEnum(orderMessage.getOrderStatus());
			orderService.updateStatusByOrderSnList(Collections.singletonList(order.getOrderSn()), orderSubStatusNew, orderSubStatusOld, OperateSourceConstants.OPERATION_CHANNEL, OrderOperateConstants.CHANNEL_PART_SEND, null);
		}
		Order order = SupplyCollectionUtils.getSingleDataFirst(orderList, Order::new);
		supplyChainMQProducer.orderAlterSend(order.getSupplyTradeSn(), order.getServerName());
		//售后处理
		this.afterSaleHandle(order);
		return Boolean.TRUE;
	}
}
